using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Nextensions.IO
{
	public class FileSystem
	{
		//private static readonly string _ext = @"\.(?<ext>[^\.]+$)";

		public struct Error
		{
			public string Description;
		}

		public static void MakeWritable(string Path)
		{
			if (File.Exists(Path))
			{
				FileInfo file = new FileInfo(Path);
				bool readOnly = (file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;

				if (!readOnly)
				{
					return;
				}

				try
				{
					file.Attributes -= FileAttributes.ReadOnly;
				}
				catch (Exception) {}
			}
			else if (Directory.Exists(Path))
			{
				DirectoryInfo dir = new DirectoryInfo(Path);
				bool readOnly = (dir.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;

				if (!readOnly)
				{
					return;
				}

				try
				{
					dir.Attributes -= FileAttributes.ReadOnly;
				}
				catch (Exception) {}
			}
		}

		public static void DeleteFile(string FileName)
		{
			MakeWritable(FileName);

			try
			{
				File.Delete(FileName);
			}
			catch (Exception) {}
		}

		public static void CreateDirectory(string Path)
		{
			try
			{
				Directory.CreateDirectory(Path);
			}
			catch (Exception) {}
		}

		public static bool DeleteDirectory(string Path)
		{
			if (!Directory.Exists(Path))
			{
				return false;
			}

			DirectoryInfo[] subdirs = new DirectoryInfo(Path).GetDirectories();

			foreach (DirectoryInfo dir in subdirs)
			{
				EmptyDirectory(dir.FullName);
				Directory.Delete(dir.FullName);
			}

			try
			{
				Directory.Delete(Path);
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static bool EmptyDirectory(string path)
		{
			if (!Directory.Exists(path))
			{
				return false;
			}

			string[] files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);

			foreach (string fileName in files)
			{
				try
				{
					MakeWritable(fileName);
					File.Delete(fileName);
				}
				catch
				{
					return false;
				}
			}

			string[] directories = Directory.GetDirectories(path, "*", SearchOption.AllDirectories);

			foreach (string directoryName in directories)
			{
				try
				{
					MakeWritable(directoryName);
					Directory.Delete(directoryName);
				}
				catch
				{
					return false;
				}
			}

			return true;
		}

		public static void CopyFile(string Source, string Target)
		{
			try
			{
				MakeWritable(Target);
				File.Copy(Source, Target, true);
			}
			catch (Exception) {}
		}

		public static string GetHighestFile(string FilePath)
		{
			string highFile = FilePath;
			int highNum = -1;
			Match num;

			foreach (string file in Directory.GetFiles(Directory.GetParent(FilePath).FullName, "*" + Regex.Match(FilePath, @"\.([^\.\\\/]+)$").Groups[1].Value, SearchOption.TopDirectoryOnly))
			{
				num = Regex.Match(file, @"(?<num>\d+)[^\\\/]*$");
				if (!num.Success)
				{
					continue;
				}
				if (int.Parse(num.Groups["num"].Value) > highNum)
				{
					highFile = file;
				}
			}
			return highFile;
		}

		public static string NameFromPath(string Path)
		{
			return Regex.Match(Path, @"(^|\\|\/)(?<end>[^\\]+)$").Groups["end"].Value;
		}

		public static string ApplicationDirectory
		{
			get
			{
				return Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName;
			}
		}

        public static string IncrementFileName(string FileName)
        {
            int index = 0;
            string newName = FileName;

            while (File.Exists(newName))
            {
                index++;
                newName = Regex.Replace(FileName, @"^(?<n>.+?)(?<ext>\.[^\.]+)?$", String.Format("${{n}} ({0})${{ext}}", index));
            }

            return newName;
        }

		public static string[] SplitTextFile(string Path, long Size, string StartFromAndAppend, string EndAtAndAppend,string EndAt)
		{
			FileInfo file = new FileInfo(Path);
			char[] charBuffer;
			string[] @out = new string[file.Length / Size];

			StreamReader reader = new StreamReader(Path, true);

			long charCount = 0;

			while(!reader.EndOfStream)
			{
				charCount ++;
				reader.Read();
			}

			Console.WriteLine(charCount);
			charBuffer = new char[charCount];
			reader.Close();
			reader = new StreamReader(Path,true);

//			reader.Read(reader.CurrentEncoding.GetByteCount())

			reader.Close();

			return @out;
		}

		private static long GetCharCount(Encoding encoding, long bytes)
		{
			if (encoding.CodePage == Encoding.ASCII.CodePage)
			{
				return bytes;
			}
			else if (encoding.CodePage == Encoding.Unicode.CodePage)
			{
				return bytes / 2;
			}
			else
			{
				return bytes;
			}
		}
	}
}